package com.googlecode.garbagecan.test.socket.nio;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.googlecode.garbagecan.test.socket.SerializableUtil;

public class MyServer2 {

	private final static Logger logger = Logger.getLogger(MyServer2.class.getName());
	
	public static void main(String[] args) throws IOException {
		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
		serverSocketChannel.socket().setReuseAddress(true);
		serverSocketChannel.socket().bind(new InetSocketAddress(10000));
		
		while (true) {
			SocketChannel socketChannel = serverSocketChannel.accept();
			invoke(socketChannel);
		}
	}

	private static void invoke(final SocketChannel socketChannel) throws IOException {
		new Thread(new Runnable() {
			public void run() {
				try {
					MyRequestObject myRequestObject = receiveData(socketChannel);
					logger.log(Level.INFO, myRequestObject.toString());
					
					MyResponseObject myResponseObject = new MyResponseObject(
							"response for " + myRequestObject.getName(), 
							"response for " + myRequestObject.getValue());
					sendData(socketChannel, myResponseObject);
				} catch (Exception ex) {
					logger.log(Level.SEVERE, null, ex);
				} finally {
					try {
						socketChannel.close();
					} catch(Exception ex) {}
				}
			}

			private MyRequestObject receiveData(SocketChannel socketChannel) throws IOException {
				MyRequestObject myRequestObject = null;
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				ByteBuffer buffer = ByteBuffer.allocate(1024);
				
				try {
					byte[] bytes;
					int size = 0;
					while ((size = socketChannel.read(buffer)) >= 0) {
						buffer.flip();
						bytes = new byte[size];
						buffer.get(bytes);
						baos.write(bytes);
						buffer.clear();
					}
					bytes = baos.toByteArray();
					Object obj = SerializableUtil.toObject(bytes);
					myRequestObject = (MyRequestObject)obj;
				} finally {
					try {
						baos.close();
					} catch(Exception ex) {}
				}
				return myRequestObject;
			}

			private void sendData(SocketChannel socketChannel, MyResponseObject myResponseObject) throws IOException {
				byte[] bytes = SerializableUtil.toBytes(myResponseObject);
				ByteBuffer buffer = ByteBuffer.wrap(bytes);
				socketChannel.write(buffer);
			}
			
		}).start();
	}
}
